package org.moth.seq;

import org.moth.clock.SystemClock;

/**
 * @Auther: tuzhe.wxm
 * @Date: 2019/5/23 09:40
 * @Description:
 */
public class LightSequence implements Sequence{

    //起始时间 （2017-01-01 01-01-01）
    private static final long twepoch = 1558576112897L;
    //时间戳+ 12

    /* 上次生成ID的时间截 */
    private long lastTimestamp = -1L;
    /* 毫秒内序列(0~4095) */
    private long sequence = 0L;

    //序列号位数
    private static final long sequenceBits = 12l;
    /* 生成序列的掩码，这里为4095 (0b111111111111=4095) */
    private static final long sequenceMask = -1L ^ (-1L << sequenceBits);
    //时间戳位偏移量
    private static final long timestampShift =  sequenceBits ;//  + 12

    @Override
    public long next() {
        long timestamp = this.currentTimestamp();

        // 如果当前时间小于上一次ID生成的时间戳，说明系统时钟回退过这个时候应当抛出异常
        //系统处理闰秒， 正闰秒 和 负闰秒之分， 目前出现的都是正闰秒
        if(timestamp < lastTimestamp){
            try {
                wait(1000L);
                timestamp = this.currentTimestamp();
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }

        // 如果是同一时间生成的，则进行毫秒内序列
        if(timestamp == lastTimestamp){
            sequence = (sequence + 1) & sequenceMask;
            //毫秒内序列溢出
            if(sequence == 0){
                // 阻塞到下一个毫秒,获得新的时间戳
                timestamp = this.untilNextMillis(lastTimestamp);
            }
        }else{// 时间戳改变，毫秒内序列重置
            sequence = 0;
        }

        //生成的时间戳已经成为过去式
        lastTimestamp = timestamp;

        final long currentSequenceId = ((timestamp - twepoch) << timestampShift) | sequence;
        return currentSequenceId;
    }


    protected long untilNextMillis(long lastTimestamp) {
        long timestamp = this.currentTimestamp();
        while (timestamp <= lastTimestamp) {
            timestamp = this.currentTimestamp();
        }
        return timestamp;
    }

    private long currentTimestamp(){

        return SystemClock.currentTimestamp();
    }
}
